home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / program / vol15n10.zip / MULTIL.ZIP / MLSRC.ZIP / MSDEV / PROJECTS / MLAUNCH / MLAUNCH.CPP < prev    next >
C/C++ Source or Header  |  1996-04-14  |  12KB  |  440 lines

  1.  
  2. // MultiLaunch Shell Extension
  3. // (C)1996 By John Lam
  4.  
  5. #include "stdafx.h"
  6. #include <windows.h>
  7. #include <initguid.h>
  8. #include <shlobj.h>
  9. #include "Resource.h"
  10. #include "MLaunch.h"
  11.  
  12. /////////////////////////////////////////////////////////////////////////////
  13. // Nonmember function prototypes
  14.  
  15. STDAPI DllGetClassObject (REFCLSID, REFIID, LPVOID*);
  16. STDAPI DllCanUnloadNow ();
  17. STDAPI DllRegisterServer ();
  18. STDAPI DllUnregisterServer ();
  19.  
  20. void UpdateRegistry(BOOL);
  21. HKEY CreateRegKey(CString, CString);
  22. void DeleteRegKey(CString);
  23. void CreateRegValue(HKEY, CString, CString);
  24.  
  25. UINT CALLBACK AfxPropPageCallback(HWND, UINT message, LPPROPSHEETPAGE pPropPage);
  26. UINT CALLBACK PropPageCallback(HWND, UINT message, LPPROPSHEETPAGE pPropPage);
  27.  
  28. // Helper functions
  29. CString GetFilenameExtension(CString);
  30.  
  31. /////////////////////////////////////////////////////////////////////////////
  32. // Global variables
  33.  
  34. UINT        g_cRefThisDll = 0;          // Reference count for this DLL
  35.  
  36. /////////////////////////////////////////////////////////////////////////////
  37. // Exported functions
  38.  
  39. STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppvObj)
  40. {
  41.     *ppvObj = NULL; 
  42.     if (rclsid != CLSID_MultiLaunchPropSheet)
  43.         return CLASS_E_CLASSNOTAVAILABLE;
  44.  
  45.     CClassFactory* pClassFactory = new CClassFactory;
  46.  
  47.     if (pClassFactory == NULL)
  48.         return E_OUTOFMEMORY;
  49.  
  50.     HRESULT hr = pClassFactory->QueryInterface (riid, ppvObj);
  51.     pClassFactory->Release ();
  52.     return hr;
  53. }
  54.  
  55. STDAPI DllCanUnloadNow ()
  56. {
  57.     return (g_cRefThisDll == 0) ? S_OK : S_FALSE;
  58. }
  59.  
  60. STDAPI DllRegisterServer(void)
  61. {
  62.     // Code to autoregister the server into the registry
  63.     UpdateRegistry(TRUE);
  64.     return S_OK;
  65. }
  66.  
  67. STDAPI DllUnregisterServer(void)
  68. {
  69.     UpdateRegistry(FALSE);
  70.     return S_OK;
  71. }
  72.  
  73. // Helper function that registers and unregisters the DLL
  74. void UpdateRegistry(BOOL Register)
  75. {
  76.     HKEY hKey;
  77.  
  78.     CString strCLSID = STRCLSID_MultiLaunchPropSheet; 
  79.     CString strProgID = STRPROGID_MultiLaunchPropSheet;
  80.     CString strDescription = STRDESCRIPTION_MultiLaunchPropSheet;
  81.     CString strFilename;
  82.  
  83.     // Get the full path to this dll
  84.     GetModuleFileName(AfxGetInstanceHandle(), strFilename.GetBuffer(260), 260);
  85.     strFilename.ReleaseBuffer();
  86.  
  87.     if (Register) {
  88.  
  89.         // Register the DLL
  90.  
  91.         (void) CreateRegKey(strProgID, strDescription);
  92.         (void) CreateRegKey(strProgID + "\\CLSID", strCLSID);
  93.         (void) CreateRegKey("CLSID\\" + strCLSID, strDescription);
  94.         (void) CreateRegKey("CLSID\\" + strCLSID + "\\ProgID", strProgID);
  95.         hKey = CreateRegKey("CLSID\\" + strCLSID + "\\InProcServer32", strFilename);
  96.         CreateRegValue(hKey, "ThreadingModel", "Apartment");
  97.  
  98.         // Register the Context Menu Handler
  99.  
  100.         (void) CreateRegKey("*\\shellex\\ContextMenuHandlers\\" + strProgID, strCLSID);
  101.         
  102.         // Register the Property Sheet Handler
  103.         
  104.         (void) CreateRegKey("*\\shellex\\PropertySheetHandlers\\" + strProgID, strCLSID);
  105.  
  106.     }
  107.     else {
  108.  
  109.         // Unregister the DLL
  110.  
  111.         DeleteRegKey(strProgID);
  112.         DeleteRegKey(strProgID + "\\CLSID");
  113.         DeleteRegKey("CLSID\\" + strCLSID);
  114.         DeleteRegKey("CLSID\\" + strCLSID + "\\ProgID");
  115.         DeleteRegKey("CLSID\\" + strCLSID + "\\InProcServer32");
  116.  
  117.         // Unregister the Context Menu Handler
  118.  
  119.         DeleteRegKey("*\\shellex\\ContextMenuHandlers\\" + strProgID);
  120.  
  121.         // Unregister the Property Sheet Handler
  122.  
  123.         DeleteRegKey("*\\shellex\\PropertySheetHandlers\\" + strProgID);
  124.     }
  125. }
  126.  
  127. // Helper functions for creating and destroying registry keys
  128. HKEY CreateRegKey(CString strKey, CString strValue)
  129. {
  130.     HKEY hKey;
  131.     DWORD Disposition;
  132.  
  133.     RegCreateKeyEx(HKEY_CLASSES_ROOT, strKey, 0, strValue.LockBuffer(), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &Disposition);
  134.     strValue.UnlockBuffer();
  135.     RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE*)strValue.LockBuffer(), strValue.GetLength() + 1);
  136.     strValue.UnlockBuffer();
  137.  
  138.     return hKey;
  139. }
  140.  
  141. void DeleteRegKey(CString strKey)
  142. {
  143.     RegDeleteKey(HKEY_CLASSES_ROOT, strKey);
  144. }
  145.  
  146. void CreateRegValue(HKEY hKey, CString strValueName, CString strValue)
  147. {
  148.     RegSetValueEx(hKey, strValueName, 0, REG_SZ, (BYTE*)strValue.LockBuffer(), strValue.GetLength() + 1);
  149.     strValue.UnlockBuffer();
  150. }
  151.  
  152. /////////////////////////////////////////////////////////////////////////////
  153. // CClassFactory member functions
  154.  
  155. CClassFactory::CClassFactory ()
  156. {
  157.     m_cRef = 1;
  158.     g_cRefThisDll++;
  159. }
  160.  
  161. CClassFactory::~CClassFactory ()
  162. {
  163.     g_cRefThisDll--;
  164. }
  165.  
  166. STDMETHODIMP CClassFactory::QueryInterface (REFIID riid, LPVOID* ppvObj)
  167. {
  168.     *ppvObj = NULL;
  169.     HRESULT hr = E_NOINTERFACE;
  170.  
  171.     if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
  172.         *ppvObj = this;
  173.         hr = NOERROR;
  174.         m_cRef++;
  175.     }
  176.     return hr;
  177. }
  178.  
  179. STDMETHODIMP_(ULONG) CClassFactory::AddRef ()
  180. {
  181.     return ++m_cRef;
  182. }
  183.  
  184. STDMETHODIMP_(ULONG) CClassFactory::Release ()
  185. {
  186.     if (--m_cRef == 0)
  187.         delete this;
  188.     return m_cRef;
  189. }
  190.  
  191. STDMETHODIMP CClassFactory::CreateInstance (LPUNKNOWN pUnkOuter, REFIID riid,
  192.     LPVOID* ppvObj)
  193. {
  194.     *ppvObj = NULL;
  195.     if (pUnkOuter != NULL)
  196.         return CLASS_E_NOAGGREGATION;
  197.  
  198.     CShellExtension* pShellExtension = new CShellExtension;
  199.  
  200.     if (pShellExtension == NULL)
  201.         return E_OUTOFMEMORY;
  202.  
  203.     HRESULT hr = pShellExtension->QueryInterface (riid, ppvObj);
  204.     if (hr == S_OK)
  205.         pShellExtension->Release ();
  206.     return hr;
  207. }
  208.  
  209. STDMETHODIMP CClassFactory::LockServer (BOOL fLock)
  210. {
  211.     return E_NOTIMPL;
  212. }
  213.  
  214. /////////////////////////////////////////////////////////////////////////////
  215. // CShellExtension member functions
  216.  
  217. CShellExtension::CShellExtension ()
  218. {
  219.     // !!!!! BUG
  220.     // VC++ 4.0 Incorrectly decrements m_cRef 1 too many times when building
  221.     // a Win32 Debug version of the application. The macro here detects and adjusts
  222.     // the number to 2 when we are building the debug version of the application
  223.     // The reason for this is unknown.
  224.  
  225. /* #ifdef _DEBUG
  226.     m_cRef = 2;                // BUG! in DEBUG build
  227. #endif
  228.  
  229. #ifndef _DEBUG
  230.     m_cRef = 1;                // Correctly compiled in RELEASE build
  231. #endif */
  232.  
  233.     // The above bug is FIXED in VC++ 4.1!! Hooray!
  234.     //ASSERT(FALSE);
  235.     m_cRef = 1;
  236.  
  237.     g_cRefThisDll++;
  238. }
  239.  
  240. CShellExtension::~CShellExtension ()
  241. {
  242.     g_cRefThisDll--;
  243. }
  244.  
  245. STDMETHODIMP CShellExtension::QueryInterface (REFIID riid, LPVOID* ppvObj)
  246. {
  247.     *ppvObj = NULL;
  248.     HRESULT hr = E_NOINTERFACE;
  249.  
  250.     if (riid == IID_IUnknown) {
  251.         *ppvObj = (LPUNKNOWN) (LPSHELLPROPSHEETEXT) this;
  252.         hr = NOERROR;
  253.         m_cRef++;
  254.     }
  255.     else if (riid == IID_IShellPropSheetExt) {
  256.         *ppvObj = (LPSHELLPROPSHEETEXT) this;
  257.         hr = NOERROR;
  258.         m_cRef++;
  259.     }
  260.     else if (riid == IID_IShellExtInit) {
  261.         *ppvObj = (LPSHELLEXTINIT) this;
  262.         hr = NOERROR;
  263.         m_cRef++;
  264.     }
  265.     else if (riid == IID_IContextMenu) {
  266.         *ppvObj = (LPCONTEXTMENU) this;
  267.         hr = NOERROR;
  268.         m_cRef++;
  269.     }
  270.     return hr;
  271. }
  272.  
  273. STDMETHODIMP_(ULONG) CShellExtension::AddRef ()
  274. {
  275.     return ++m_cRef;
  276. }
  277.  
  278. STDMETHODIMP_(ULONG) CShellExtension::Release ()
  279. {
  280.     if (--m_cRef == 0)
  281.         delete this;
  282.     return m_cRef;
  283. }
  284.  
  285. STDMETHODIMP CShellExtension::AddPages (LPFNADDPROPSHEETPAGE lpfnAddPage,
  286.     LPARAM lParam)
  287. {
  288.     HPROPSHEETPAGE hPage;
  289.  
  290.     CMLPage* pMLPage = new CMLPage;
  291.  
  292.     // Setup reference counting 
  293.     pMLPage->m_psp.pcRefParent = &g_cRefThisDll;
  294.     pMLPage->m_psp.dwFlags = pMLPage->m_psp.dwFlags | PSP_USEREFPARENT;
  295.  
  296.     // Hook into the PropPageCallback so that I can destroy the CMLPage object
  297.     // when Windows destroys the window represented by CMLPage.
  298.     pMLPage->m_psp.pfnCallback = PropPageCallback;
  299.  
  300.     // Save filename in the Property Page Class CMLPage
  301.     pMLPage->SetFilename(m_szFile);
  302.     
  303.     hPage = CreatePropertySheetPage (&pMLPage->m_psp);
  304.     
  305.     if (hPage != NULL)
  306.         if (!lpfnAddPage (hPage, lParam))
  307.             DestroyPropertySheetPage (hPage);
  308.  
  309.     return NOERROR;
  310. }
  311.     
  312. STDMETHODIMP CShellExtension::ReplacePage (UINT uPageID,
  313.     LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam)
  314. {
  315.     return E_FAIL;
  316. }
  317.  
  318. STDMETHODIMP CShellExtension::Initialize (LPCITEMIDLIST pidlFolder,